﻿#region Original Work By Marcelo Chavez
//---------------------------------------------------------------------------------------------------
//
//  This library is based on original work by Marcelo Chavez.
//  Please see http://www.codeproject.com/KB/miscctrl/lcars_net_controls.aspx
//  for more information.
//
//---------------------------------------------------------------------------------------------------
#endregion

using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System;

namespace Streambolics.Lcars
{
    /// <summary>
    ///     The base class for all LCARS controls.
    /// </summary>

    // TODO: See what happens if we use a Control instead of a UserControl here.

    public class LcarsControl : Control
    {
        // TODO: Embed the font, following http://www.bobpowell.net/embedfonts.htm
        private static Font _LcarsFont = new Font ("LCARS", 14, FontStyle.Regular);

        private Function _Function = Function.Miscellaneous;
        private bool _Online = true;
        private bool _UseAlternateColor = false;
        private bool _Highlighted = false;
        
        public LcarsControl ()
        {
            BackColor = Color.Black;
            ForeColor = Color.White;
            Font = _LcarsFont;

            SetStyle (ControlStyles.DoubleBuffer, true);
            SetStyle (ControlStyles.AllPaintingInWmPaint, true);
            SetStyle (ControlStyles.ResizeRedraw, true);
        }

        /// <summary>
        ///     The color associated with the current function and status
        ///     of the control.
        /// </summary>
        /// <returns>
        ///     The color to use. The output is typically used to create a brush
        ///     to paint the active portion of a control.
        /// </returns>
        /// <seealso>GetFunctionBrush</seealso>

        public Color GetFunctionColor ()
        {
            if (!Enabled)
            {
                return ColorName.Unavailable;
            }

            if (!_Online)
            {
                return ColorName.Offline;
            }

            if (_UseAlternateColor)
            {
                return Color.White;
            }

            // TODO: Make this an extension method of Function.

            switch (_Function)
            {
                case Function.Critical:
                    return ColorName.Critical;
                case Function.Display:
                    return ColorName.Display;
                case Function.Miscellaneous:
                    return ColorName.Miscellaneous;
                case Function.Navigation:
                    return ColorName.Navigation;
                case Function.Primary:
                    return ColorName.Primary;
                case Function.Static1:
                    return ColorName.Static1;
                case Function.Static2:
                    return ColorName.Static2;
                case Function.System:
                    return ColorName.System;
            }

            return Color.White;
        }

        /// <summary>
        ///     A brush to paint the functional part of the control.
        /// </summary>
        /// <returns></returns>

        protected Brush GetFunctionBrush ()
        {
            return new SolidBrush (GetFunctionColor ());
        }

        /// <summary>
        ///     A brush to paint the non-functional background part of the control.
        /// </summary>
        /// <returns></returns>

        protected Brush GetBackgroundBrush ()
        {
            return new SolidBrush (BackColor);
        }

        #region Function

        protected virtual void OnFunctionChanged (EventArgs e)
        {
            Invalidate ();
        }

        [Category ("Behavior")]
        [Description ("Function of this control. This in turn determines its color.")]
        public Function Function
        {
            get
            {
                return _Function;
            }
            set
            {
                if (_Function != value)
                {
                    _Function = value;
                    OnFunctionChanged (EventArgs.Empty);
                }
            }
        }

        #endregion

        #region Online

        [Category("Behavior")]
        public bool Online
        {
            get
            {
                return _Online;
            }
            set
            {
                if (_Online != value)
                {
                    _Online = value;
                    Invalidate ();
                }
            }
        }

        #endregion

        /// <summary>
        ///     Whether to use the alternate color.
        /// </summary>
        /// <remarks><para>
        ///     This feature is used by the blinking state
        /// </para></remarks>
        protected bool UseAlternateColor
        {
            get
            {
                return _UseAlternateColor;
            }
            set
            {
                _UseAlternateColor = value;
            }
        }

        #region Highlighted

        protected virtual void OnHighlightedChanged (EventArgs e)
        {
            Invalidate ();
        }

        protected bool Highlighted
        {
            get
            {
                return _Highlighted;
            }
            set
            {
                if (_Highlighted != value)
                {
                    _Highlighted = value;
                    OnHighlightedChanged (EventArgs.Empty);
                }
            }
        }

        #endregion

        protected override void OnEnabledChanged (System.EventArgs e)
        {
            base.OnEnabledChanged (e);
            Invalidate ();
        }

        protected virtual void DoRenderFunction (Graphics g, Brush BackBrush, Brush FunctionBrush)
        {
        }

        protected override void OnPaint (PaintEventArgs e)
        {
            base.OnPaint (e);
            Graphics g = e.Graphics;

            // TODO: Expose those two so they can be changed by the designer.

            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;

            using (Brush bb = GetBackgroundBrush ())
            {
                using (Brush fb = GetFunctionBrush ())
                {
                    DoRenderFunction (g, bb, fb);
                }
            }
        }
    }
}
